package com.zx.scp.service.impl;

import java.math.BigDecimal;
import java.text.MessageFormat;
import java.text.ParseException;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;

import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.TransactionCallback;
import org.springframework.transaction.support.TransactionTemplate;

import com.alipay.api.AlipayApiException;
import com.zx.map.dao.model.ActiveRedpacket;
import com.zx.map.dao.model.MerchantInfo;
import com.zx.map.dao.model.MessageInfo;
import com.zx.map.dao.model.Redpacket;
import com.zx.map.dao.model.SettleType;
import com.zx.map.service.ActiveRedpacketService;
import com.zx.map.service.BaseAcctInfoService;
import com.zx.map.service.CustAcctLogService;
import com.zx.map.service.EncashLogService;
import com.zx.map.service.MerchantInfoService;
import com.zx.map.service.MerchantOfflineConfigInfoService;
import com.zx.map.service.MessageInfoService;
import com.zx.map.service.OrdLogService;
import com.zx.map.service.RedpacketService;
import com.zx.map.service.SettleTypeService;
import com.zx.map.service.UserCountService;
import com.zx.map.service.model.BaseAcctInfoModel;
import com.zx.map.service.model.CustAcctLogModel;
import com.zx.map.service.model.EncashLogModel;
import com.zx.map.service.model.EncashResponse;
import com.zx.map.service.model.MerchantInfoDetailModel;
import com.zx.map.service.model.MerchantInfoModel;
import com.zx.map.service.model.MerchantOfflineConfigInfoModel;
import com.zx.map.service.model.OrdLogModel;
import com.zx.map.utils.MyBeanUtils;
import com.zx.map.utils.SUConstants;
import com.zx.mobile.MobileCommonHelper;
import com.zx.mobile.PayRateHelper;
import com.zx.mobile.domain.EncashApplyDomain;
import com.zx.mobile.domain.MobileUserDomain;
import com.zx.mobile.service.proxy.EncashCommonProxy;
import com.zx.platform.utils.AlipayUtil;
import com.zx.scp.service.IncomHandleService;
import com.zx.scp.service.model.OrderPayCallBackModel;

/**
 * Created by bibei on 2017/2/17.
 */
@Service
public class IncomHandleServiceImpl implements IncomHandleService {
	/**
	 * log
	 */
	private static Logger log = Logger.getLogger(IncomHandleServiceImpl.class);
	@Autowired
	private UserCountService userCountService;
	private final static String MESSAGE = "尊敬的{0}，\n你有一笔收款交易\n" + "交易金额：{1}\n交易类型：微信支付\n" + "交易时间：{2}";

	private final static String MESSAGE_TRADE = "尊敬的{0}，\n你有一笔收款交易\n" + "交易金额：{1}\n交易类型：{2}\n" + "交易时间：{3}";
	@Autowired
	private OrdLogService ordLogService;
	@Autowired
	private MerchantInfoService merchantInfoService;
	@Autowired
	private BaseAcctInfoService baseAcctInfoService;
	@Autowired
	private TransactionTemplate transactionTemplate;
	@Autowired
	private CustAcctLogService custAcctLogService;
	@Autowired
	private MerchantOfflineConfigInfoService merchantOfflineConfigInfoService;
	@Autowired
	private SettleTypeService settleTypeService;

	@Autowired
	private MessageInfoService messageInfoService;
	@Autowired
	private EncashLogService encashLogService;

	@Autowired
	private ActiveRedpacketService activeRedpacketService;
	@Autowired
	private RedpacketService redpacketService;
	/**
	 * 处理订单
	 * 
	 * @param orderPayCallBackModel
	 * @return
	 */
	public String handleOrderCallBack(final OrderPayCallBackModel orderPayCallBackModel) {
		List<SettleType> list = settleTypeService.list();
		Map<Integer, SettleType> settleTypeMap = new HashMap<Integer, SettleType>();
		for (SettleType s : list) {
			settleTypeMap.put(s.getId(), s);
		}

		String returnCode = (String) transactionTemplate.execute(new TransactionCallback<Object>() {
			@Override
			public Object doInTransaction(TransactionStatus arg0) {
				// 获取订单信息 如果该订单已经为终态 不做任何处理 否则进行更新操作 并加行锁
				OrdLogModel tempOrd = ordLogService.selectByPrimaryKeyAndLineLock(orderPayCallBackModel.getOrdId());
				if (null != tempOrd) {
					if (!("S".equals(tempOrd.getTransStatus()) || "F".equals(tempOrd.getTransStatus()))) {
						tempOrd.setPaymentId(orderPayCallBackModel.getPaymentId());
						tempOrd.setPaymentAmt(orderPayCallBackModel.getPaymentAmt());
						// 下动态设置
						// tempOrd.setPaymentType("2");
						tempOrd.setTransStatus(orderPayCallBackModel.getTransStatus());
						tempOrd.setPaymentTime(orderPayCallBackModel.getPaymentTime());
						tempOrd.setUpdateDate(new Date());
						// 如果交易成功 记录账户余额 余额=交易金额*(1-扣率)
						// 计算结算金额 支付金额 - 商户手续费

						// 获取费率
						String amt = orderPayCallBackModel.getPaymentAmt().toString();
						String rate = null;
//						String transType = tempOrd.getTransType();// 支付方式 线下和线上扫码
						String payType =tempOrd.getPaymentType();
						List<MerchantInfo> miList = merchantInfoService.getById(tempOrd.getMerchantId());
						if (miList != null && miList.size() > 0) {
							
							//payType返回参数发生变化
							
							if (SUConstants.paymentTypeWX.equals(payType)) {
								rate = String.valueOf(
										settleTypeMap.get(miList.get(0).getSettleRateType()).getValue1() * 0.01);
							} else if (SUConstants.paymentTypeAlipay.equals(payType)) {
								rate = String.valueOf(
										settleTypeMap.get(miList.get(0).getSettleRateType()).getValue2() * 0.01);
							}
						} else {
							throw new RuntimeException("客户不存在");
						}

						// if (SUConstants.TRANSTYPE_INCOME.equals(transType)
						// || SUConstants.TRANSTYPE_RECHARGE.equals(transType)) { // 线上扫码
						// if (SUConstants.paymentTypeAlipay.equals(payType)) {
						// // 2016.10.28 0.6改成0.5
						// rate = PayRateHelper.INCOMERATEALIPAY;
						// } else if (SUConstants.paymentTypeWX.equals(payType)) {
						// rate = PayRateHelper.INCOMERATEWX;
						// } else {
						// rate = PayRateHelper.INCOMERATE;
						// }
						// } else if (SUConstants.TRANSTYPE_OFFLINE_INCOME.equals(transType)) {
						// MerchantOfflineConfigInfoModel offlineConfigInfoModel =
						// merchantOfflineConfigInfoService
						// .getModelByKey(tempOrd.getMerchantId());
						// if (null != offlineConfigInfoModel) {
						// if (null != offlineConfigInfoModel.getPayRate()) {
						// log.info("按线下费率计算：" + offlineConfigInfoModel.getPayRate());
						// rate = new BigDecimal(offlineConfigInfoModel.getPayRate().toString())
						// .divide(new BigDecimal("100")).toString();
						// } else {
						// rate = PayRateHelper.INCOMERATE;
						// }
						// String wxNotifyPayType = "微信支付";
						// if (SUConstants.paymentTypeAlipay.equals(payType)) {
						// wxNotifyPayType = "支付宝";
						// } else if (SUConstants.paymentTypeWX.equals(payType)) {
						// wxNotifyPayType = "微信支付";
						// }
						// // 微信通知
						// String msg = MessageFormat.format(MESSAGE,
						// offlineConfigInfoModel.getMerchantShortName(), tempOrd.getPaymentAmt(),
						// wxNotifyPayType, tempOrd.getPaymentTime());
						// WXNotifyUtils.sendNotify(offlineConfigInfoModel.getNotifyWxid(), "交易提醒",
						// msg);
						// } else {
						// rate = PayRateHelper.INCOMERATE;
						// }
						// }

						BigDecimal feeAmt = new BigDecimal(amt).multiply(new BigDecimal(rate)).setScale(2,
								BigDecimal.ROUND_UP);
						tempOrd.setFeeAmt(feeAmt.doubleValue());
						tempOrd.setBgAccountId(orderPayCallBackModel.getUserId());
						ordLogService.update(tempOrd);
						// 如果交易成功 记录账户余额 余额=交易金额*(1-扣率)

						// 用户消费统计表维护 add by Max.Wang
						tempOrd.setUserId(orderPayCallBackModel.getUserId());
						tempOrd.setUserName(orderPayCallBackModel.getUserName());
						userCountService.update(tempOrd);

						if ("S".equals(orderPayCallBackModel.getTransStatus())) {
							BigDecimal settleAmt = new BigDecimal(amt).subtract(feeAmt).setScale(2,
									BigDecimal.ROUND_DOWN);
							// 对账户信息增加行锁
							BaseAcctInfoModel acct = baseAcctInfoService
									.getModelByKeyAndLineLock(tempOrd.getMerchantId());
							baseAcctInfoService.addBaseAcctBalByKeyModel(settleAmt, acct);
							// 增加账户明细记录
							CustAcctLogModel custModel = transformCustAcct(acct, tempOrd, settleAmt);
							custAcctLogService.add(custModel);

							// 处理高迁收益入代理人账户
							try {
								// 1、获取代理账户信息 并计算高迁金额
								BigDecimal subRate = new BigDecimal(rate)
										.subtract(new BigDecimal(PayRateHelper.INCOMERATE));
								if (subRate.compareTo(new BigDecimal("0")) > 0) {
									log.info("记录代理高迁金额，高迁费率:" + subRate);
									MerchantInfoModel agentMerchantInfo = merchantInfoService
											.getMerchantInfoModelBySysAccount(tempOrd.getAgentSysAccount());
									if (null != agentMerchantInfo) {
										BigDecimal subPayAmount = subRate.multiply(new BigDecimal(amt)).setScale(2,
												BigDecimal.ROUND_DOWN);
										// 对账户信息增加行锁
										BaseAcctInfoModel agentAcct = baseAcctInfoService
												.getModelByKeyAndLineLock(agentMerchantInfo.getMerchantId());
										baseAcctInfoService.addBaseAcctBalByKeyModel(subPayAmount, agentAcct);
										// 增加账户明细记录
										CustAcctLogModel agentCustAcct = addAgentCustAcct(agentAcct, tempOrd,
												subPayAmount);
										custAcctLogService.add(agentCustAcct);
									}
								}
							} catch (Exception e) {
								log.error("系统内部异常 ", e);
							}
							
							// 交易成功给商户添加一条交易消息。注：目前没有做推送直接插入消息到数据库
							try {
								MessageInfo messageInfo = new MessageInfo();
								messageInfo.setMerchantId(tempOrd.getMerchantId());
								messageInfo.setOrderId(tempOrd.getOrdId());
								messageInfo.setMessageType(SUConstants.MESSAGE_TYPE_TRADE);
//								MerchantOfflineConfigInfoModel offlineConfigInfoModel = merchantOfflineConfigInfoService
//										.getModelByKey(tempOrd.getMerchantId());
								String msg = MessageFormat.format(MESSAGE_TRADE,
										miList.get(0).getLegalName(), tempOrd.getPaymentAmt(),
										"2".equals(tempOrd.getPaymentType() ) ? "微信" : "支付宝", tempOrd.getPaymentTime());
								messageInfo.setMessage(msg);
								messageInfo.setSendDatetime(new Date());
								messageInfo.setTransType(tempOrd.getPaymentType());
								messageInfoService.sendMessage(messageInfo);
								//处理红包相关信息
								dealRedpacket(tempOrd);

							} catch (Throwable e) {
								log.error("系统内部异常 ", e);
							}

							// add by max 自动提现操作

							MobileUserDomain user = new MobileUserDomain();
							MerchantInfoDetailModel detail = merchantInfoService
									.getMerchantDetail(tempOrd.getMerchantId());
							user.setMerchantInfoDetailModel(detail);

							EncashApplyDomain encashApplyDomain = new EncashApplyDomain();
							encashApplyDomain.setEncashAmt(settleAmt.toString());

							if (miList.get(0).getSettleRateType() == 1) {
								encashApplyDomain.setEncashType(MobileCommonHelper.ENCASHTYPE_T0);
							} else if (miList.get(0).getSettleRateType() == 2) {
								encashApplyDomain.setEncashType(MobileCommonHelper.ENCASHTYPE_T1);
							} else if (miList.get(0).getSettleRateType() == 3) {
								encashApplyDomain.setEncashType(MobileCommonHelper.ENCASHTYPE_T3);
							}

							EncashLogModel param = EncashCommonProxy.transformEncachLog(user, encashApplyDomain);
							EncashResponse encashResponse = new EncashResponse();
							// T+0取现 结算
							if (MobileCommonHelper.ENCASHTYPE_T0.equals(encashApplyDomain.getEncashType())) {
								encashResponse = encashLogService.dealEncashLogT0(param,
										user.getMerchantInfoDetailModel().getSettleCardInfoModel());
							} else {
								encashResponse = encashLogService.dealEncashLogT1(param,
										user.getMerchantInfoDetailModel().getSettleCardInfoModel());
							}

						}

					} else {
						log.info("订单已是终态不做处理" + MyBeanUtils.beanToJson(orderPayCallBackModel));
					}

					return SUConstants.CODE_SUCCESS_VALUE;
				} else {
					log.error("异常订单,未发现订单，订单信息如下：" + MyBeanUtils.beanToJson(orderPayCallBackModel));
					return SUConstants.CODE_FAIL_VALUE;
				}

			}
		});
		return returnCode;
	}

	private void dealRedpacket(OrdLogModel tempOrd) throws AlipayApiException, ParseException {
		BigDecimal paymentMoney = new BigDecimal(tempOrd.getPaymentAmt());
		//如果是支付宝，满足红包领取条件反现
		
		Map<String, Object> redAndActive = activeRedpacketService.getActiveRedpacketByUseMoney(tempOrd.getMerchantId(), tempOrd.getBgAccountId(), new BigDecimal(tempOrd.getPaymentAmt()));
		if(!redAndActive.isEmpty() && redAndActive.containsKey("redpacket") && redAndActive.containsKey("activeRedpacket")) {
			Redpacket redpacket = (Redpacket) redAndActive.get("redpacket");
			ActiveRedpacket activeRedpacket = (ActiveRedpacket) redAndActive.get("activeRedpacket");
			
			//订单金额大于满减要求且是支付宝支付，反现给支付宝
			if("1".equals(tempOrd.getPaymentType()) && paymentMoney.compareTo(redpacket.getUseMoney()) >= 0) {
				AlipayUtil.refundOrder(tempOrd.getOrdId(), redpacket.getMoney().toString());
				activeRedpacket.setIsUsed(true);
				activeRedpacket.setUsedDatetime(new Date());
				activeRedpacket.setOrdId(tempOrd.getOrdId());
				activeRedpacketService.update(activeRedpacket);
				//更新红包活动的信息
				int useNum = redpacket.getUseNum() + 1;
				redpacket.setUseNum(useNum);
				BigDecimal activeMoney = redpacket.getActiveMoney().add(paymentMoney);
				redpacket.setActiveMoney(activeMoney);
				
				redpacketService.update(redpacket);
				//修改订单金额
				tempOrd.setRedpacketRefund(redpacket.getMoney());
				ordLogService.update(tempOrd);
				paymentMoney = paymentMoney.subtract(redpacket.getMoney());
			}
		}
		//判断是否可以领取优惠券
		Map<String, Object> params = new HashMap<>();
		params.put("merchantId", tempOrd.getMerchantId());
		
		params.put("totalMoney", paymentMoney);
		params.put("userId", tempOrd.getBgAccountId());
		activeRedpacketService.sendRedpacket(params);
	}
	public static CustAcctLogModel transformCustAcct(BaseAcctInfoModel baseModel, OrdLogModel tempOrd,
			BigDecimal settleAmt) {
		CustAcctLogModel temp = new CustAcctLogModel();
		temp.setAcctBal(baseModel.getAvlBal());
		temp.setAcctType("B");
		temp.setCreateDate(new Date());
		temp.setCustId(tempOrd.getMerchantId());
		temp.setCustSysaccount(tempOrd.getMerSysAccount());
		temp.setOrdId(tempOrd.getOrdId());
		temp.setRemark(tempOrd.getPaymentType());// 增加交易方式
		temp.setOriginalAmt(tempOrd.getPaymentAmt());// 增加账户变化原始交易金额
		temp.setTransAmt(settleAmt.doubleValue());// 记录账户变化余额
		temp.setTransType(tempOrd.getTransType());
		return temp;
	}

	/**
	 * 代理高迁费率计算
	 *
	 * @param baseModel
	 * @param tempOrd
	 * @param settleAmt
	 * @return
	 */
	public static CustAcctLogModel addAgentCustAcct(BaseAcctInfoModel baseModel, OrdLogModel tempOrd,
			BigDecimal settleAmt) {
		CustAcctLogModel temp = new CustAcctLogModel();
		temp.setAcctBal(baseModel.getAvlBal());
		temp.setAcctType("B");
		temp.setCreateDate(new Date());
		temp.setCustId(tempOrd.getMerchantId());
		temp.setCustSysaccount(tempOrd.getMerSysAccount());
		temp.setOrdId(tempOrd.getOrdId());
		temp.setRemark(tempOrd.getPaymentType());// 增加交易方式
		temp.setOriginalAmt(tempOrd.getPaymentAmt());// 增加账户变化原始交易金额
		temp.setTransAmt(settleAmt.doubleValue());// 记录账户变化余额
		temp.setTransType(SUConstants.TRANSTYPE_AGENT_PROMATION);
		return temp;
	}
}
